/*  Back Orifice 2000 - Remote Administration Suite
    Copyright (C) 1999, Cult Of The Dead Cow

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

	The author of this program may be contacted at dildog@l0pht.com. */

#include <windows.h> 
#include <winperf.h> 
#include <perfdata.h>
#include <stdlib.h> 
 
 
LPTSTR      *gPerfTitleSz; 
LPTSTR      TitleData; 
 
 
// GetPerfData() - Get a new set of performance data. 
//      *ppData should be NULL initially. 
//      This function will allocate a buffer big enough to hold the 
//      data requested by szObjectIndex. 
// 
//      *pDataSize specifies the initial buffer size.  If the size is 
//      too small, the function will increase it until it is big enough 
//      then return the size through *pDataSize.  Caller should 
//      deallocate *ppData if it is no longer being used. 
// 
//      Returns ERROR_SUCCESS if no error occurs. 
// 
//      Note: the trial and error loop is quite different from the normal 
//            registry operation.  Normally if the buffer is too small, 
//            RegQueryValueEx returns the required size.  In this case, 
//            the perflib, since the data is dynamic, a buffer big enough 
//            for the moment may not be enough for the next. Therefor, 
//            the required size is not returned. 
// 
//            One should start with a resonable size to avoid the overhead 
//            of reallocation of memory. 

DWORD GetPerfData (HKEY hPerfKey, LPTSTR szObjectIndex, PPERF_DATA *ppData, DWORD *pDataSize)
{ 	
	DWORD   DataSize; 
	DWORD   dwR; 
	DWORD   Type; 
	
    if (!*ppData) 
        *ppData = (PPERF_DATA) LocalAlloc (LMEM_FIXED, *pDataSize); 	
	
    do  { 
        DataSize = *pDataSize; 
        dwR = RegQueryValueEx (hPerfKey, 
			szObjectIndex, 
			NULL, 
			&Type, 
			(BYTE *)*ppData, 
			&DataSize); 
		
        if (dwR == ERROR_MORE_DATA) 
		{ 
            LocalFree (*ppData); 
            *pDataSize += 1024; 
            *ppData = (PPERF_DATA) LocalAlloc (LMEM_FIXED, *pDataSize); 
		} 
		
        if (!*ppData) 
		{ 
            LocalFree (*ppData); 
            return ERROR_NOT_ENOUGH_MEMORY; 
		} 
		
	} while (dwR == ERROR_MORE_DATA); 
	
    return dwR; 
} 
 
 
 
 
#ifdef UNICODE 
 
#define atoi    atoiW 
 
//  atoiW() - Unicode version of atoi. 

INT atoiW (LPTSTR s) 
{ 	
	INT i = 0; 
	
	while (iswdigit (*s)) { 
		i = i*10 + (BYTE)*s - L'0'; 
        s++; 
	} 
	
    return i; 
} 
 
#endif 
 
 
 
 
//  GetPerfTitleSz() - Retrieves the performance data title strings. 
// 
//   This call retrieves english version of the title strings. 
// 
//   For NT 3.1, the counter names are stored in the "Counters" value 
//   in the ...\perflib\009 key.  For 3.5 and later, the 009 key is no 
//      longer used.  The counter names should be retrieved from "Counter 009" 
//      value of HKEY_PERFORMANCE_KEY. 
// 
//      Caller should provide two pointers, one for buffering the title 
//      strings the other for indexing the title strings.  This function will 
//      allocate memory for the TitleBuffer and TitleSz.  To get the title 
//      string for a particular title index one would just index the TitleSz. 
//      *TitleLastIdx returns the highest index can be used.  If TitleSz[N] is 
//      NULL then there is no Title for index N. 
// 
//      Example:  TitleSz[20] points to titile string for title index 20. 
// 
//      When done with the TitleSz, caller should LocalFree(*TitleBuffer). 
// 
//      This function returns ERROR_SUCCESS if no error. 

DWORD   GetPerfTitleSz (HKEY    hKeyMachine, 
                        HKEY    hKeyPerf, 
                        LPTSTR  *TitleBuffer, 
                        LPTSTR  *TitleSz[], 
                        DWORD   *TitleLastIdx) 
{ 
	HKEY  hKey1; 
	HKEY    hKey2; 
	DWORD   Type; 
	DWORD   DataSize; 
	DWORD   dwR; 
	DWORD   Len; 
	DWORD   Index; 
	DWORD   dwTemp; 
	BOOL    bNT10; 
	LPTSTR  szCounterValueName; 
	LPTSTR  szTitle; 
	
    // Initialize 
    // 
    hKey1        = NULL; 
    hKey2        = NULL; 
    *TitleBuffer = NULL; 
    *TitleSz     = NULL; 
	
    // Open the perflib key to find out the last counter's index and system version. 
    
	dwR = RegOpenKeyEx (hKeyMachine, 
		TEXT("software\\microsoft\\windows nt\\currentversion\\perflib"), 
		0, 
		KEY_READ, 
		&hKey1); 
    if (dwR != ERROR_SUCCESS) 
        goto done; 
	
    // Get the last counter's index so we know how much memory to allocate for TitleSz 
    
	DataSize = sizeof (DWORD); 
    dwR = RegQueryValueEx (hKey1, TEXT("Last Counter"), 0, &Type, (LPBYTE)TitleLastIdx, &DataSize); 
    if (dwR != ERROR_SUCCESS) 
        goto done; 
	
    // Find system version, for system earlier than 1.0a, there's no version value. 
    
	dwR = RegQueryValueEx (hKey1, TEXT("Version"), 0, &Type, (LPBYTE)&dwTemp, &DataSize); 
	
    if (dwR != ERROR_SUCCESS) 
        // unable to read the value, assume NT 1.0 
        bNT10 = TRUE; 
    else 
        // found the value, so, NT 1.0a or later 
        bNT10 = FALSE; 
	

	
    // Now, get ready for the counter names and indexes. 
    
	if (bNT10) 
	{ 
        // NT 1.0, so make hKey2 point to ...\perflib\009 and get 
        //  the counters from value "Counters" 
        // 
        szCounterValueName = TEXT("Counters"); 
        dwR = RegOpenKeyEx (hKeyMachine, 
			TEXT("software\\microsoft\\windows nt\\currentversion\\perflib\\009"), 
			0, 
			KEY_READ, 
			&hKey2); 
        if (dwR != ERROR_SUCCESS) 
            goto done; 
	} 
    else 
	{ 
        // NT 1.0a or later.  Get the counters in key HKEY_PERFORMANCE_KEY 
        //  and from value "Counter 009" 
    
		szCounterValueName = TEXT("Counter 009"); 
        hKey2 = hKeyPerf; 
	} 
	

	
    // Find out the size of the data. 
    // 
    dwR = RegQueryValueEx (hKey2, szCounterValueName, 0, &Type, 0, &DataSize); 
    if (dwR != ERROR_SUCCESS) 
        goto done; 

	
    // Allocate memory 
    // 
    *TitleBuffer = (LPTSTR)LocalAlloc (LMEM_FIXED, DataSize); 
    if (!*TitleBuffer) 
	{ 
        dwR = ERROR_NOT_ENOUGH_MEMORY; 
        goto done; 
	} 
	
    *TitleSz = (LPTSTR *)LocalAlloc (LPTR, (*TitleLastIdx+1) * sizeof (LPTSTR)); 
    if (!*TitleSz) 
	{ 
        dwR = ERROR_NOT_ENOUGH_MEMORY; 
        goto done; 
	} 
	
	
	// Query the data 
 
	dwR = RegQueryValueEx (hKey2, szCounterValueName, 0, &Type, (BYTE *)*TitleBuffer, &DataSize); 
    if (dwR != ERROR_SUCCESS) 
        goto done; 
	
	
	// Setup the TitleSz array of pointers to point to beginning of each title string. 
    // TitleBuffer is type REG_MULTI_SZ. 
    
	szTitle = *TitleBuffer; 
	
    while (Len = lstrlen (szTitle)) 
	{ 
        Index = atoi (szTitle); 
		
        szTitle = szTitle + Len +1; 
		
        if (Index <= *TitleLastIdx) 
            (*TitleSz)[Index] = szTitle; 
		
        szTitle = szTitle + lstrlen (szTitle) +1; 
	} 
	
	
	
done: 
	
    // Done. Now cleanup! 
    
	if (dwR != ERROR_SUCCESS) 
	{ 
        // There was an error, free the allocated memory 
        // 
        if (*TitleBuffer) LocalFree (*TitleBuffer); 
        if (*TitleSz)     LocalFree (*TitleSz); 
	} 
	
    // Close the hKeys. 

    if (hKey1) RegCloseKey (hKey1); 
    if (hKey2 && hKey2 != hKeyPerf) RegCloseKey (hKey2); 

	
    return dwR; 
} 

 

